<template>
  <a-card
    style="height: 100%; width: 100%"
    :body-style="{ height: '100%', padding: '10px' }"
    class="sql-card"
  >
    <div style="height: 50%; width: 100%">
      <a-row :span="24" style="height: 100%">
        <a-col :span="6" style="height: 100%">
          <a-card
            :body-style="{ height: 'calc( 100% - 50px )', padding: '5px' }"
            style="margin-right: 10px; height: 100%"
            size="small"
          >
            <template #title
              ><a-dropdown :trigger="['click']">
                <a
                  class="ant-dropdown-link"
                  style="
                    width: 30px;
                    text-align: center;
                    display: block;
                    line-height: 32px;
                    color: rgba(0, 0, 0, 0.85);
                  "
                  @click.prevent
                >
                  {{ currentDataSource == null ? '数据源' : currentDataSource }}
                  <s-icon type="down-outlined"></s-icon>
                </a>
                <template #overlay>
                  <a-menu>
                    <template v-for="(item, index) in datasources" :key="`menu_${index}`">
                      <a-menu-item>
                        <a
                          @click="
                            () => {
                              currentDataSource = item
                              loadTables()
                            }
                          "
                          >{{ item }}</a
                        >
                      </a-menu-item>
                      <a-menu-divider />
                    </template>
                  </a-menu>
                </template> </a-dropdown
            ></template>
            <template #extra
              ><s-input
                v-model="searchText"
                size="small"
                style="width: 120px"
                allow-clear
                placeholder="表名"
              ></s-input
            ></template>
            <s-scroll style="height: 100%">
              <template v-for="(item, index) in tableList" :key="`tableList_${index}`">
                <a
                  v-if="
                    searchText == null || searchText.length == 0 || item.indexOf(searchText) > -1
                  "
                  class="item"
                  :style="{
                    width: '100%',
                    padding: '5px',
                    width: '100%',
                    display: 'block',
                    color: ' rgba(0,0,0,.85)'
                  }"
                  @click="appendToDoc(item)"
                >
                  <s-icon type="eye-outlined" @click.stop="loadTableStruct(item)"></s-icon>
                  {{ item }}
                </a>
              </template>
            </s-scroll>
          </a-card>
        </a-col>
        <a-col :span="18" style="height: 100%">
          <a-row :span="24">
            <a-col :span="12">
              <s-button
                type="text"
                icon="caret-right-outlined"
                style="color: #096dd9"
                :loading="loading"
                @click="runSql"
                >运行</s-button
              >
              <s-button type="text" icon="clear-outlined" @click="formatSql">格式化</s-button>
              <a-popover trigger="click">
                <template #title><s-icon type="plus-outlined" @click="addParam"></s-icon></template>
                <template #content>
                  <s-scroll style="height: 300px; width: 200px">
                    <template v-for="(item, index) in params" :key="`params_${index}`">
                      <div style="width: 100%; padding: 5px">
                        <a-tag>{{ index + 1 }}</a-tag>
                        <s-input v-model="item.value" style="width: calc(100% - 50px)" size="small">
                        </s-input>
                        <s-icon
                          type="close-outlined"
                          @click="
                            () => {
                              params.splice(index, 1)
                            }
                          "
                        ></s-icon>
                      </div>
                    </template>
                  </s-scroll>
                </template>
                <s-button type="text" icon="font-colors-outlined" @click="formatSql">
                  <template v-if="params.length > 0">
                    <a-badge :count="params.length" size="small" :offset="[10, 0]"> 变量 </a-badge>
                  </template>
                  <template v-else>变量</template>
                </s-button>
              </a-popover>
            </a-col>

            <a-col :span="12">
              <a-row type="flex" justify="end">
                <a-space class="operator"> <seconds ref="seconds" /></a-space>
              </a-row>
            </a-col>
          </a-row>
          <div className="codemirror">
            <sql-editor ref="sqlEditor" :doc="sql" :focus-init="true"> </sql-editor>
          </div>
        </a-col>
      </a-row>
    </div>
    <div ref="tableOuter" style="height: 50%; width: 100%">
      <s-tabs
        ref="tabs"
        size="small"
        style="height: 100%; width: 100%"
        type="editable-card"
        hide-add
        @edit="removeTableStruct"
      >
        <a-tab-pane key="0" tab="执行结果" style="height: 100%" :closable="false">
          <s-scroll v-if="errMsg != null">
            <div v-if="errMsg != null" class="ant-typography">
              {{ errMsg }}
            </div>
          </s-scroll>

          <s-table
            v-else-if="columns.length > 0"
            ref="table"
            :value="tableData"
            bordered
            :scroll="{
              y: tableHeight
            }"
            row-key="result_rowkey"
            :pageable="false"
            :columns="columns"
            size="small"
            :check-enable="false"
          >
          </s-table>
        </a-tab-pane>
        <a-tab-pane
          v-for="(item, index) in tableStructs"
          :key="`struct_${index}`"
          :closable="true"
          style="height: 100%"
        >
          <template #tab>
            <s-icon type="redo-outlined" @click="refreshTableStruct(item.title, item.db)"></s-icon>
            {{ item.title }}
          </template>
          <s-table
            ref="table"
            :value="item.data"
            bordered
            :scroll="{
              y: tableHeight
            }"
            :loading="item.loading"
            row-key="COLUMN_NAME"
            :pageable="false"
            :columns="tableStructColumn"
            size="small"
            :check-enable="false"
          >
            <template #bodyCell="{ column, record }">
              <template
                v-if="column.dataIndex === 'COLUMN_SIZE' || column.dataIndex === 'DECIMAL_DIGITS'"
              >
                {{ record[column.dataIndex] == 0 ? '' : record[column.dataIndex] }}
              </template>
            </template>
          </s-table>
        </a-tab-pane>
      </s-tabs>
    </div>
  </a-card>
</template>

<script lang="ts">
import SqlEditor from '@/components/SqlEditor/index.vue'
import { getCurrentInstance, ref } from 'vue'
import { format } from 'sql-formatter'
import { message } from 'ant-design-vue'
import Seconds from './Seconds.vue'
export default {
  components: { Seconds, SqlEditor },
  setup(props) {
    const searchText = ref('')
    const tableList = ref([])
    const context = getCurrentInstance()?.appContext.config.globalProperties
    let columns = ref<any>([])
    let tableData = ref([])
    const seconds = ref(null)
    const sql = ref('')
    let tableHeight = ref(200)
    const datasources = ref([])
    const loading = ref(false)
    const currentDataSource = ref(null)
    const params = ref<any>([])
    const errMsg = ref(null)
    const tableStructs = ref<any>([])
    const tabs = ref(null)
    const tableStructColumn = ref([
      {
        title: '名',
        dataIndex: 'COLUMN_NAME',
        ellipsis: true
      },
      {
        title: '类型',
        dataIndex: 'TYPE_NAME',
        ellipsis: true
      },
      {
        title: '长度',
        dataIndex: 'COLUMN_SIZE',
        ellipsis: true
      },
      {
        title: '小数点',
        dataIndex: 'DECIMAL_DIGITS',
        ellipsis: true
      },
      {
        title: '可为空',
        dataIndex: 'IS_NULLABLE',
        ellipsis: true
      },
      {
        title: '注释',
        dataIndex: 'REMARKS',
        ellipsis: true
      }
    ])
    const sqlEditor = ref(null)
    const formatSql = () => {
      let sqlContent = sqlEditor.value.getDoc() || ''
      sqlContent = format(sqlContent, { language: 'mysql' })
      sql.value = sqlContent
    }
    const loadTables = () => {
      context?.$api.GET('/toolkit/sql/tables', { dbName: currentDataSource.value }).then((res) => {
        tableList.value = res.data
      })
    }
    const loadDataSources = () => {
      context?.$api.GET('/toolkit/sql/datasources').then((res) => {
        datasources.value = res.data
        if (datasources.value.length > 0) {
          currentDataSource.value = datasources.value[0]
          loadTables()
        }
      })
    }
    const appendToDoc = (str) => {
      let sqlContent = sqlEditor.value.getDoc() || ''
      sql.value = sqlContent + str
    }
    const toggleTab = (key) => {
      ;(tabs.value as any).toggleTab(key)
    }
    const refreshTableStruct = (str, db) => {
      let tableStruct = null
      for (let p = 0; p < tableStructs.value.length; p++) {
        if (tableStructs.value[p].title == str && tableStructs.value[p].db == db) {
          tableStruct = tableStructs.value[p]
          break
        }
      }
      if (tableStruct != null) {
        tableStruct.loading = true
        context?.$api
          .GET('/toolkit/sql/tableStruct', { dbName: db, tableName: str })
          .then((res) => {
            tableStruct.loading = false
            tableStruct.data = res.data
          })
          .catch((e) => {
            tableStruct.loading = false
          })
      }
    }
    const loadTableStruct = (str) => {
      let db = currentDataSource.value
      if (db == null) {
        message.warn('请先选择数据源!')
        return
      }
      let index = -1
      for (let p = 0; p < tableStructs.value.length; p++) {
        if (tableStructs.value[p].title == str && tableStructs.value[p].db == db) {
          index = p
          break
        }
      }
      if (index > -1) {
        toggleTab('struct_' + index)
      } else {
        context?.$loading(true)
        context?.$api
          .GET('/toolkit/sql/tableStruct', { dbName: currentDataSource.value, tableName: str })
          .then((res) => {
            context?.$loading(false)
            tableStructs.value.push({
              title: str,
              data: res.data,
              db: db,
              loading: false
            })
            toggleTab('struct_' + (tableStructs.value.length - 1))
          })
          .catch((e) => {
            context?.$loading(false)
          })
      }
    }
    const addParam = () => {
      params.value.push({
        value: ''
      })
    }
    const removeTableStruct = (key) => {
      let index = parseInt(key.substr('struct_'.length))
      tableStructs.value.splice(index, 1)
      const tabsValue = tabs.value as any
      let activeIndex =
        tabsValue.activeKey?.length > 1
          ? parseInt(tabsValue.activeKey.substr('struct_'.length))
          : -1
      if (activeIndex > -1) {
        if (activeIndex > tableStructs.value.length - 1) {
          activeIndex = tableStructs.value.length - 1
        }
        if (activeIndex >= 0) {
          toggleTab('struct_' + activeIndex)
        } else {
          toggleTab('0')
        }
      } else {
        toggleTab('0')
      }
    }
    const runSql = () => {
      if (currentDataSource.value == null) {
        message.warn('请先选择数据源!')
        return
      }
      let sqlContent = sqlEditor.value.getDoc()
      if (sqlContent.length == 0) {
        message.warn('请输入sql!')
        return
      }
      const paramsV: Array<any> = []
      params.value.forEach((v) => {
        paramsV.push(v.value)
      })
      loading.value = true
      ;(seconds.value as any).startCount()
      context?.$api
        .PUT('/toolkit/sql/runSql', {
          db: currentDataSource.value,
          sql: sqlContent,
          params: paramsV
        })
        .then((res) => {
          ;(seconds.value as any).endCount()
          loading.value = false
          errMsg.value = res.data.errMsg
          if (res.data.errMsg == null) {
            const newHeaders: Array<any> = []
            res.data.headers.forEach((header) => {
              newHeaders.push({
                title: header,
                dataIndex: header,
                ellipsis: true,
                resizable: true,
                width: 200
              })
            })
            let i = 1
            res.data.rows.forEach((row) => {
              row.result_rowkey = i
              i++
            })
            columns.value = newHeaders
            tableData.value = res.data.rows
          }
          toggleTab('0')
        })
        .catch((e) => {
          loading.value = false
          ;(seconds.value as any).clear()
        })
    }
    loadDataSources()
    return {
      sqlEditor,
      sql,
      seconds,
      tableList,
      columns,
      loadTableStruct,
      tableHeight,
      formatSql,
      runSql,
      removeTableStruct,
      tableStructColumn,
      tableStructs,
      currentDataSource,
      datasources,
      params,
      tableData,
      addParam,
      loading,
      errMsg,
      searchText,
      loadTables,
      tabs,
      refreshTableStruct,
      appendToDoc
    }
  },
  mounted() {
    ;(this as any).tableHeight = (this as any).$refs.tableOuter.offsetHeight - 90
  }
}
</script>
<style lang="less" scoped>
/* 这个$props没有写错,不要改 */
.sql-card {
  ::v-deep(.cm-editor) {
    height: 100%;
    font-size: 18px;
  }
  .item:hover {
    background-color: #f5f5f5;
  }
  .item {
    color: rgba(0, 0, 0, 0.85);
  }
  ::v-deep(.ant-tabs-content-holder) {
    height: 100%;
  }
  ::v-deep(.ant-tabs-content) {
    height: 100%;
  }

  ::v-deep(.codemirror) {
    height: calc(100% - 40px);
    border: 1px solid #d9d9d9;
  }
  ::v-deep(div.ant-tabs-content-holder div.ant-tabs-tabpane) {
    padding-left: 0px;
  }
  ::v-deep(.cm-scroller) {
    &::-webkit-scrollbar {
      height: 6px;
      width: 6px;
    }

    &::-webkit-scrollbar-thumb {
      border-radius: 10px;
      -webkit-box-shadow: inset 0 0 0px rgba(0, 0, 0, 0.2);
      background: var(--scrollbar-thumb-color);
    }

    &::-webkit-scrollbar-track {
      background: var(--scrollbar-track-color);
    }

    &::-webkit-scrollbar-corner {
      background: var(--scrollbar-track-color);
    }
  }
}
</style>
